package com.efast.dmom.mgmt.service.les.impl;

import java.util.Date;
import java.util.List;
import java.util.UUID;

import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;

import com.efast.cafe.framework.exception.ServiceException;
import com.efast.cafe.framework.jdbc.JdbcDao;
import com.efast.cafe.framework.util.SpringWebUtils;
import com.efast.dmom.mgmt.dao.les.*;
import com.efast.dmom.mgmt.dao.master.TmBasDeliveryUnitDao;
import com.efast.dmom.mgmt.dao.master.TmBasPartDao;
import com.efast.dmom.mgmt.entity.les.*;
import com.efast.dmom.mgmt.entity.master.TmBasDeliveryUnit;
import com.efast.dmom.mgmt.entity.master.TmBasPart;
import com.efast.dmom.mgmt.service.les.TwDocOrderHeaderService;
import com.efast.dmom.mgmt.utils.Assist;

/**
 * @author Administrator
 */
@Service
public class TwDocOrderHeaderServiceImpl implements TwDocOrderHeaderService {

	/**
	 * 出库订单表TW_DOC_ORDER_HEADER
	 */
	private final TwDocOrderHeaderDao twDocOrderHeaderDao;
	/**
	 * 出库订单表 TW_DOC_ORDER_DETAILS
	 */
	private final TwDocOrderDetailsDao twDocOrderDetailsDao;
	/**
	 * 拣货任务表 TW_OUTB_TASK_HEADER
	 */
	private final TwOutbTaskHeaderDao twOutbTaskHeaderDao;
	/**
	 * 拣货任务表 TW_OUTB_TASK_DETAIL
	 */
	private final TwOutbTaskDetailDao twOutbTaskDetailDao;
	/**
	 * 分配表 TW_ACT_ALLOC_LOT_D
	 */
	private final TwActAllocLotdDao twActAllocLotdDao;
	/**
	 * 库存表TW_INV_SKU_LOC_T_L
	 */
	private final TwInvSkuLoctlDao twInvSkuLoctlDao;
	/**
	 * 零件仓储关系以及动态库位入库选择规则 tr_bas_part_storage
	 */
	private final TrBasPartStorageDao trBasPartStorageDao;
	/**
	 * 出库记录表 tt_whm_stock_outbound
	 */
	private final TtWhmStockOutboundDao ttWhmStockOutboundDao;
	/**
	 * 发运记录表 tt_whm_material_send
	 */
	private final TtWhmMaterialSendDao ttWhmMaterialSendDao;
	/**
	 * 零件主数据信息 tr_bas_part
	 */
	private final TmBasPartDao trBasPartDao;
	/**
	 * 配送单位基本信息 tm_bas_delivery_unit
	 */
	private final TmBasDeliveryUnitDao tmBasDeliveryUnitDao;
	
	@Qualifier("jdbcDao")
	@Autowired
	private JdbcDao jdbcDao;

	@Autowired
	public TwDocOrderHeaderServiceImpl(TwDocOrderHeaderDao twDocOrderHeaderDao,
			TwDocOrderDetailsDao twDocOrderDetailsDao, TwOutbTaskHeaderDao twOutbTaskHeaderDao,
			TwOutbTaskDetailDao twOutbTaskDetailDao, TwActAllocLotdDao twActAllocLotdDao,
			TwInvSkuLoctlDao twInvSkuLoctlDao, TrBasPartStorageDao trBasPartStorageDao,
			TtWhmStockOutboundDao ttWhmStockOutboundDao, TtWhmMaterialSendDao ttWhmMaterialSendDao,
			TmBasPartDao trBasPartDao, TmBasDeliveryUnitDao tmBasDeliveryUnitDao) {
		this.twDocOrderHeaderDao = twDocOrderHeaderDao;
		this.twDocOrderDetailsDao = twDocOrderDetailsDao;
		this.twOutbTaskHeaderDao = twOutbTaskHeaderDao;
		this.twOutbTaskDetailDao = twOutbTaskDetailDao;
		this.twActAllocLotdDao = twActAllocLotdDao;
		this.twInvSkuLoctlDao = twInvSkuLoctlDao;
		this.trBasPartStorageDao = trBasPartStorageDao;
		this.ttWhmStockOutboundDao = ttWhmStockOutboundDao;
		this.ttWhmMaterialSendDao = ttWhmMaterialSendDao;
		this.trBasPartDao = trBasPartDao;
		this.tmBasDeliveryUnitDao = tmBasDeliveryUnitDao;
	}

	/**
	 * 按单分配 1：遍历出库单头对应的明细的每一行（每一行零件） 2：给每个零件 找 一个库位。
	 * 
	 * @param enti
	 *            enti
	 */
	@Override
	public void distributionByBill(TwDocOrderHeader enti) {

		// 【1】：根据id从出库订单表TW_DOC_ORDER_HEADER，查询出这条记录。
		TwDocOrderHeader twDocOrderHeader = twDocOrderHeaderDao.selectTwDocOrderHeaderById(
				enti.getTwDocOrderHeaderId());
		String soSheetStatus = twDocOrderHeader.getSoSheetStatus();
		if (!("0".equals(soSheetStatus) || "1".equals(soSheetStatus))) {
			throw new ServiceException("新单0,部分分配1 状态,才能按单分配");
		}

		// 【3】：根据头表的tw_doc_order_header_id和so_sheet_no 从TW_DOC_ORDER_DETAILS找出对应的出库单明细.
		List<TwDocOrderDetails> listTwDocOrderDetails = twDocOrderDetailsDao.selectTwDocOrderDetails(new Assist(
				Assist.andEq("tw_doc_order_details.tw_doc_order_header_id", twDocOrderHeader.getTwDocOrderHeaderId()),
				Assist.andEq("tw_doc_order_details.so_sheet_no", twDocOrderHeader.getSoSheetNo())));

		// 【4】：生成 拣货任务表 TW_OUTB_TASK_HEADER
		TwOutbTaskHeader twOutbTaskHeader = new TwOutbTaskHeader();
		// 拣货状态0新任务1拣货完成2部分拣货3
		twOutbTaskHeader.setInboundStatus("0");
		twOutbTaskHeader.setSoSheetNo(twDocOrderHeader.getSoSheetNo());
		// 拣货任务清单打印状态（0打印1已打印)
		twOutbTaskHeader.setPrintStatus("0");
		String pickAllocNo = jdbcDao.executeProcGetCode("tw_outb_task_header", "efast");
		// 拣货任务清单单号
		twOutbTaskHeader.setPickAllocNo(pickAllocNo);
		twOutbTaskHeader.setTaskCreateman(SpringWebUtils.getRequestUser());
		twOutbTaskHeader.setTaskCreatetime(new Date());
		twOutbTaskHeader.setMarkStatus(1);
		twOutbTaskHeader.setCompanyCode(SpringWebUtils.getRequestCompany());
		twOutbTaskHeader.setCreateUser(SpringWebUtils.getRequestUser());
		twOutbTaskHeader.setCreateTime(new Date());
		twOutbTaskHeaderDao.insertNonEmptyTwOutbTaskHeader(twOutbTaskHeader);

		// 【5】：遍历每一行，给对应的零件分配拣货的“库位”
		for (int i = 0; i < listTwDocOrderDetails.size(); i++) {
			// 出库订单表 TW_DOC_ORDER_DETAILS
			TwDocOrderDetails twDocOrderDetails = listTwDocOrderDetails.get(i);

			// SimpleDateFormat dateFm = new SimpleDateFormat("yyyy-MM-dd"); // 格式化当前系统日期
			// String dateTime = dateFm.format(new Date());
			// String lotNo = twDocOrderDetails.getPartNoVersion() + dateTime +
			// twDocOrderDetails.getLotatt04();

			// 根据零件号 去 零件仓库关系（tr_bas_part_storage）找一个库位
			List<TrBasPartStorage> listTrBasPartStorage = trBasPartStorageDao.selectTrBasPartStorage(new Assist(
					Assist.andEq("tr_bas_part_storage.part_no_version", twDocOrderDetails.getPartNoVersion())));

			// 分配表 TW_ACT_ALLOC_LOT_D
			TwActAllocLotd twActAllocLotd = new TwActAllocLotd();
			// 拣货任务表 TW_OUTB_TASK_DETAIL
			TwOutbTaskDetail twOutbTaskDetail = new TwOutbTaskDetail();

			// 【6】：库存表 TW_INV_SKU_LOC_T_L
			// 分配完成后的库存变化 ： 可用数量-AVAILABLE_QTY==0 , 库存数量-CUR_QTY==1 , 待出库数量-R_OUB_QTY==1
			// 分配数量-R_ALLOC_QTY == 1 , 出库订单分配数量-SO_R_ALLOC_QTY == 1 , 拣货数量-R_PICK_QTY == 0
			// 出库订单拣货数量-SO_R_PICK_QTY == 0
			List<TwInvSkuLoctl> listTwInvSkuLoctl = twInvSkuLoctlDao.selectTwInvSkuLoctl(new Assist(
					Assist.andEq("tw_inv_sku_loc_t_l.tm_bas_storage_id", listTrBasPartStorage.get(0).getLocId()),
					Assist.andEq("tw_inv_sku_loc_t_l.part_no_version", twDocOrderDetails.getPartNoVersion())));
			if (listTwInvSkuLoctl.size() == 0) {
				// 分配的库位在库存表中没有记录
				throw new ServiceException("库存表中没有零件=" + twDocOrderDetails.getPartNoVersion() + "并且库位id="
						+ listTrBasPartStorage.get(0).getLocId());
			}

			TwInvSkuLoctl twInvSkuLoctl = listTwInvSkuLoctl.get(0);
			// 可用数量-AVAILABLE_QTY
			twInvSkuLoctl.setAvailableQty(twInvSkuLoctl.getAvailableQty() - twDocOrderDetails.getSoReqQty());
			// 库存数量-CUR_QTY
			// twInvSkuLoctl.setrOubQty(twDocOrderDetails.getSoReqQty());
			// 待出库数量-R_OUB_QTY
			twInvSkuLoctl.setrOubQty(twDocOrderDetails.getSoReqQty());
			// 分配数量-R_ALLOC_QTY
			twInvSkuLoctl.setrAllocQty(twDocOrderDetails.getSoReqQty());
			// 出库订单分配数量-SO_R_ALLOC_QTY
			twInvSkuLoctl.setSorAllocQty(twDocOrderDetails.getSoReqQty());
			// 拣货数量-R_PICK_QTY
			twInvSkuLoctl.setrPickQty(0);
			// 出库订单拣货数量-SO_R_PICK_QTY
			twInvSkuLoctl.setSorPickQty(0);
			twInvSkuLoctlDao.updateNonEmptyTwInvSkuLoctlById(twInvSkuLoctl);

			// 【7】：生成 拣货任务表 明细 TW_OUTB_TASK_DETAIL
			BeanUtils.copyProperties(twDocOrderDetails, twOutbTaskDetail);
			twOutbTaskDetail.setTwOutbTaskHeaderId(twOutbTaskHeader.getTwOutbTaskHeaderId());
			twOutbTaskDetail.setSoLineno(i + 1);
			// 待拣货仓储单元id
			twOutbTaskDetail.setPreTmBasStorageId(listTrBasPartStorage.get(0).getLocId());
			// 要求分配数量 <--要求发货数量(soReqQty)
			twOutbTaskDetail.setPreAllocQty(twDocOrderDetails.getSoReqQty());
			// 实际分配数量 <--要求发货数量(soReqQty)
			twOutbTaskDetail.setAllocQty(twDocOrderDetails.getSoReqQty());
			// 要求分配包装数
			twOutbTaskDetail.setPreAllocPackNum(twDocOrderDetails.getSoPackageNum());
			// 实际分配包装数量
			twOutbTaskDetail.setAllocPackNum(twDocOrderDetails.getSoPackageNum());
			// 要求分配包装代码
			twOutbTaskDetail.setPreAllocPack(twDocOrderDetails.getSoPackageNo());
			// 实际分配包装代码
			twOutbTaskDetail.setAllocPack(twDocOrderDetails.getSoPackageNo());
			// 分配类型（0出库订单分配1翻包补货分配2补货分配）
			twOutbTaskDetail.setAllocType("0");
			// 拣货任务标签打印状态（0打印 1已打印）
			twOutbTaskDetail.setPrintStatus("0");
			// 任务标签打印状态（0打印 1已打印）
			twOutbTaskDetail.setTaskPrintStatus("0");
			// 分配明细id
			twOutbTaskDetail.setTwActAllocLotdId(twActAllocLotd.getTwActAllocLotdId());
			// 拣货状态（新任务0，任务完成1，2部分拣货）
			twOutbTaskDetail.setPickStatus("0");
			twOutbTaskDetail.setLineno(i + 1);
			// 拣货任务清单单号
			twOutbTaskDetail.setPickAllocNo(pickAllocNo);
			twOutbTaskDetail.setDestLocId(listTrBasPartStorage.get(0).getLocId());
			// 库内跟踪流水号码
			twOutbTaskDetail.setInbSerialNo(twInvSkuLoctl.getInbSerialNo());
			// 批次号
			twOutbTaskDetail.setLotNo(twInvSkuLoctl.getLotNo());
			// 零件包装流水号
			twOutbTaskDetail.setPartPackSerial(twInvSkuLoctl.getPartPackSerial());
			// 出库时间
			twOutbTaskDetail.setOutboundTime(twDocOrderDetails.getSoSendTime());
			// 出库人
			twOutbTaskDetail.setOutboundMan(SpringWebUtils.getRequestUser());
			twOutbTaskDetail.setMarkStatus(1);
			twOutbTaskDetail.setCreateTime(new Date());
			twOutbTaskDetail.setCreateUser(SpringWebUtils.getRequestUser());
			twOutbTaskDetail.setCompanyCode(SpringWebUtils.getRequestCompany());
			twOutbTaskDetailDao.insertNonEmptyTwOutbTaskDetail(twOutbTaskDetail);

			// 【8】：向分配表 TW_ACT_ALLOC_LOT_D 插入数据
			BeanUtils.copyProperties(twDocOrderDetails, twActAllocLotd);
			// 待拣货仓储单元ID
			twActAllocLotd.setPreTmBasStorageId(listTrBasPartStorage.get(0).getLocId());
			// 实际拣货仓储单元ID
			twActAllocLotd.setActTmBasStorageId(listTrBasPartStorage.get(0).getLocId());
			twActAllocLotd.setPartNoVersion(twDocOrderDetails.getPartNoVersion());
			twActAllocLotd.setLotNo(twInvSkuLoctl.getLotNo());
			// 分配类型（0出库订单分配1翻包补货分配2补货分配）
			twActAllocLotd.setAllocType("0");
			// 装箱标签打印状态（0打印1已打印）
			twActAllocLotd.setTaskPrintStatus("0");
			// 状态（新建0、拣货任务产生1、部分拣货2、拣货完成3、关闭4）
			twActAllocLotd.setItemPickStatus("1");
			twActAllocLotd.setTwOutbTaskDetailId(twOutbTaskDetail.getTwOutbTaskDetailId());
			// 装箱任务行号ID
			twActAllocLotd.setTwOutbTaskHeaderId(twOutbTaskHeader.getTwOutbTaskHeaderId());
			// 补货任务表头ID
			twActAllocLotd.setTwDocOrderHeaderId(twDocOrderDetails.getTwDocOrderHeaderId());
			// SO明细ID
			twActAllocLotd.setTwDocOrderDetailsId(twDocOrderDetails.getTwDocOrderDetailsId());
			// 状态（发运任务未产生0、发运任务产生1、部分发运2、发运完成3）
			twActAllocLotd.setItemLoadStatus("0");
			// 实际分配数量
			twActAllocLotd.setAllocQty(twDocOrderDetails.getSoReceivedQty());
			// 要求分配数量
			twActAllocLotd.setPreAllocQty(twDocOrderDetails.getSoReceivedQty());
			// 实际分配包装数量
			twActAllocLotd.setAllocPackNum(twDocOrderDetails.getSoPackageNum());
			// 要求分配包装数量
			twActAllocLotd.setPreAllocPackNum(twDocOrderDetails.getSoPackageNum());
			// 实际分配供应商编号
			twActAllocLotd.setActSupplNo(twDocOrderDetails.getSupplNo());
			// 实际分配包装容量
			twActAllocLotd.setAllocPackageQty(twDocOrderDetails.getSoPackageQty());
			// 要求分配包装容量
			twActAllocLotd.setPreAllocPackageQty(twDocOrderDetails.getSoPackageQty());
			twActAllocLotd.setMarkStatus(1);
			twActAllocLotd.setCreateTime(new Date());
			twActAllocLotd.setCreateUser(SpringWebUtils.getRequestUser());
			twActAllocLotd.setCompanyCode(SpringWebUtils.getRequestCompany());
			twActAllocLotdDao.insertNonEmptyTwActAllocLotd(twActAllocLotd);

			// 【9】：更新tw_doc_order_details的状态为分配完成
			// 订单行状态（新单0、部分分配1、分配完成2、部分拣货3、拣货完成4、订单取消9、关闭10、分配失败11）
			twDocOrderDetails.setLineStatus("2");
			// 实际分配数量 == 要求发货数量
			twDocOrderDetails.setAllocQty(twDocOrderDetails.getSoReqQty());
			// 实际分配包装代码 == 要求发货包装编号
			twDocOrderDetails.setAllocPack(twDocOrderDetails.getSoPackageNo());
			// 实际分配包装数 == 要求发货箱数
			twDocOrderDetails.setAllocPackNum(twDocOrderDetails.getSoPackageNum());
			twDocOrderDetailsDao.updateNonEmptyTwDocOrderDetailsById(twDocOrderDetails);
		}

		// 【2】：更新TW_DOC_ORDER_HEADER的状态-->分配完成
		TwDocOrderHeader twDocOrderHeader2 = new TwDocOrderHeader();
		twDocOrderHeader2.setTwDocOrderHeaderId(enti.getTwDocOrderHeaderId());
		// SO单证状态（新单0、部分分配1、分配完成2、部分拣货3、拣货完成4、部分装箱5、装箱完成6、部分发运7、发运完成8、订单取消9、单证关闭10）
		twDocOrderHeader2.setSoSheetStatus("2");
		twDocOrderHeaderDao.updateNonEmptyTwDocOrderHeaderById(twDocOrderHeader2);

	}

	/**
	 * 确认发运 涉及到的表： 出库订单表 TW_DOC_ORDER_HEADER、TW_DOC_ORDER_DETAILS 拣货任务表 TW_OUTB_TASK_HEADER、TW_OUTB_TASK_DETAIL， 分配表
	 * TW_ACT_ALLOC_LOT_D 库存表 TW_INV_SKU_LOC_T_L 出库记录表 tt_whm_stock_outbound 发运记录表 tt_whm_material_send
	 */
	@Override
	public void shipment(TwDocOrderHeader twDocOrderHeader, List<TwDocOrderDetails> listTwDocOrderDetails) {

		// 【1】：更新TW_DOC_ORDER_HEADER的状态-->发运完成
		// SO单证状态（新单0、部分分配1、分配完成2、部分拣货3、拣货完成4、部分装箱5、装箱完成6、部分发运7、发运完成8、订单取消9、单证关闭10）
		twDocOrderHeader.setSoSheetStatus("8");
		twDocOrderHeaderDao.updateNonEmptyTwDocOrderHeaderById(twDocOrderHeader);

		// 如果没有传detail的值，说明是整单发运，如果传了说明是明细发运，可修改部分字段的值
		if (listTwDocOrderDetails.size() == 0) {
			// 【2】：根据头表的tw_doc_order_header_id和so_sheet_no 从TW_DOC_ORDER_DETAILS找出对应的出库单明细.
			listTwDocOrderDetails = twDocOrderDetailsDao.selectTwDocOrderDetails(new Assist(
					Assist.andEq("tw_doc_order_details.tw_doc_order_header_id", twDocOrderHeader.getTwDocOrderHeaderId()),
					Assist.andEq("tw_doc_order_details.so_sheet_no", twDocOrderHeader.getSoSheetNo())));
		}

		// 【3】：遍历tw_doc_order_details的每一行。
		for (TwDocOrderDetails twDocOrderDetails : listTwDocOrderDetails) {

			// 部分拣货3、拣货完成4,才能进行发运
			if (!("3".equals(twDocOrderDetails.getLineStatus()) || "4".equals(twDocOrderDetails.getLineStatus()))) {
				throw new ServiceException("只有在部分拣货，或者拣货完成才能发运");
			}

			// 【4】：更新tw_doc_order_details（出库订单表）的每一行的状态
			// 状态（发运任务未产生0、发运任务产生1、部分发运2、发运完成3）
			twDocOrderDetails.setItemLoadStatus("3");
			// 实际发货数量-->实际拣货数量
			twDocOrderDetails.setSoReceivedQty(twDocOrderDetails.getPickAllocQty());
			// 实际发货包装编号-->要求发货包装编号
			twDocOrderDetails.setSendPackageNo(twDocOrderDetails.getSoPackageNo());
			// 实际发货箱数-->实际拣货包装数
			twDocOrderDetails.setSendPackageNum(twDocOrderDetails.getPickAllocPackNum());
			twDocOrderDetailsDao.updateNonEmptyTwDocOrderDetailsById(twDocOrderDetails);

			// 【5】：更新 分配表 TW_ACT_ALLOC_LOT_D
			List<TwActAllocLotd> listTwActAllocLotd = twActAllocLotdDao.selectTwActAllocLotd(
					new Assist(Assist.andEq("tw_act_alloc_lot_d.part_no_version", twDocOrderDetails.getPartNoVersion()),
							Assist.andEq("tw_act_alloc_lot_d.so_sheet_no", twDocOrderDetails.getSoSheetNo())));
			if (listTwActAllocLotd.size() == 0) {
				throw new ServiceException("请先分配");
			}
			TwActAllocLotd twactalloclotd = new TwActAllocLotd();
			// 状态（发运任务未产生0、发运任务产生1、部分发运2、发运完成3）
			twactalloclotd.setItemLoadStatus("3");
			twactalloclotd.setTwActAllocLotdId(listTwActAllocLotd.get(0).getTwActAllocLotdId());
			twActAllocLotdDao.updateNonEmptyTwActAllocLotdById(twactalloclotd);

			// 【6】：库存表 TW_INV_SKU_LOC_T_L
			// 发运完成操作调整的库存主要是：待出库数量 需要减掉，拣货数量 需要减掉 ， 出库订单拣货数量 需要减掉 。 此操作是依据拣货完成来的。
			// 拣货数量-R_PICK_QTY == 0 ， 出库订单拣货数量-SO_R_PICK_QTY == 0 ， 待出库数量-R_OUB_QTY==0
			List<TwInvSkuLoctl> listTwInvSkuLoctl = twInvSkuLoctlDao.selectTwInvSkuLoctl(new Assist(
					Assist.andEq("tw_inv_sku_loc_t_l.tm_bas_storage_id",
							listTwActAllocLotd.get(0).getActTmBasStorageId()),
					Assist.andEq("tw_inv_sku_loc_t_l.part_no_version", twDocOrderDetails.getPartNoVersion())));
			TwInvSkuLoctl twInvSkuLoctl = listTwInvSkuLoctl.get(0);
			// twInvSkuLoctl.setAvailableQty(twInvSkuLoctl.getAvailableQty() -
			// twDocOrderDetails.getSoReceivedQty());
			// twInvSkuLoctl.setrOubQty(twInvSkuLoctl.getrOubQty() -
			// twDocOrderDetails.getSoReceivedQty());
			// twInvSkuLoctl.setrAllocQty(twInvSkuLoctl.getrAllocQty() -
			// twDocOrderDetails.getSoReceivedQty());
			// twInvSkuLoctl.setSorAllocQty(twInvSkuLoctl.getSorAllocQty() -
			// twDocOrderDetails.getSoReceivedQty());
			// 出库订单拣货数量-SO_R_PICK_QTY
			twInvSkuLoctl.setSorPickQty(0);
			// 拣货数量
			twInvSkuLoctl.setrPickQty(0);
			// 待出库数量
			twInvSkuLoctl.setrOubQty(0);
			twInvSkuLoctlDao.updateNonEmptyTwInvSkuLoctlById(twInvSkuLoctl);

			// 【7】：插入 出库记录表 tt_whm_stock_outbound
			TtWhmStockOutbound ttWhmStockOutbound = new TtWhmStockOutbound();
			List<TrBasPartStorage> listTrBasPartStorage = trBasPartStorageDao.selectTrBasPartStorage(
					new Assist(Assist.andEq("tr_bas_part_storage.suppl_no", twDocOrderDetails.getSupplNo()),
							Assist.andEq("tr_bas_part_storage.part_no_version", twDocOrderDetails.getPartNoVersion())));

			// 零件供应商关系ID
			ttWhmStockOutbound.setTrBasPartSupplId(listTrBasPartStorage.get(0).getTrBasPartSupplId());
			// 入库数量
			ttWhmStockOutbound.setOutboundQty(twDocOrderDetails.getSoReceivedQty());
			// 入库人
			ttWhmStockOutbound.setOutboundUsername(SpringWebUtils.getRequestUser());
			// 入库时间
			ttWhmStockOutbound.setOutboundTime(new Date());
			// 零件批次号
			ttWhmStockOutbound.setStockPartLotNo(listTwActAllocLotd.get(0).getLotNo());
			// 入库组号
			ttWhmStockOutbound.setOutBoundGroupId(null);
			// 仓库id
			ttWhmStockOutbound.setWarehouseId(listTrBasPartStorage.get(0).getWarehouseId());
			// 库区
			ttWhmStockOutbound.setDlocId(listTrBasPartStorage.get(0).getDlocId());
			// 库位
			ttWhmStockOutbound.setLocId(listTrBasPartStorage.get(0).getLocId());
			// 工厂
			ttWhmStockOutbound.setTmBasPlantId(listTrBasPartStorage.get(0).getTmBasPlantId());
			// 车间
			ttWhmStockOutbound.setTmBasWorkshopId(listTrBasPartStorage.get(0).getTmBasWorkshopId());
			// 对应单证编号
			ttWhmStockOutbound.setSheetNo(twDocOrderDetails.getSoSheetNo());
			// 对应单证类型
			ttWhmStockOutbound.setCommonSheetType(twDocOrderDetails.getCustSheetType());
			// ttWhmStockOutbound.setSheetId(); // 对应单证ID
			// ttWhmStockOutbound.setDlocPackageSysid(listTrBasPartStorage.get(0).getPartPackageId());
			// ttWhmStockOutbound.setInterfaceGroupId();// 接口汇总组号
			// ttWhmStockOutbound.setPoType(); // 拉动单类型
			// ttWhmStockOutbound.setVin(vin); // VIN号 预留字段 目前不用
			// ttWhmStockOutbound.setToOutboundFalg(toOutboundFalg); // 生成出库记录标记(外排序单)
			// 是否已上传SAP
			ttWhmStockOutbound.setIsTosap("0");
			// 是否允许上传SAP0不允许1允许
			ttWhmStockOutbound.setIsCanTosap("1");
			// 当前箱数
			ttWhmStockOutbound.setCurPackageNum(twDocOrderDetails.getSoPackageNum());
			List<TmBasPart> listTmBasPart = trBasPartDao.selectTmBasPart(
					new Assist(Assist.andEq("part_no_version", twDocOrderDetails.getPartNoVersion())));
			// 零件ID
			ttWhmStockOutbound.setTmBasPartId(listTmBasPart.get(0).getTmBasPartId());
			List<TmBasDeliveryUnit> listTmBasDeliveryUnit = tmBasDeliveryUnitDao.selectTmBasDeliveryUnit(
					new Assist(Assist.andEq("delivery_unit_no", twDocOrderDetails.getDeliveryRec())));
			if (listTmBasDeliveryUnit.size() == 0) {
				throw new ServiceException("无法找到发货地");
			}
			// 收货地
			ttWhmStockOutbound.setTmBasDeliveryUnitId(listTmBasDeliveryUnit.get(0).getTmBasDeliveryUnitId());
			List<TmBasDeliveryUnit> listTmBasDeliveryUnit2 = tmBasDeliveryUnitDao.selectTmBasDeliveryUnit(
					new Assist(Assist.andEq("delivery_unit_no", twDocOrderDetails.getDeliverySend())));
			if (listTmBasDeliveryUnit.size() == 0) {
				throw new ServiceException("无法找到目的地");
			}
			// 目的地
			ttWhmStockOutbound.setDeliveryRec(listTmBasDeliveryUnit2.get(0).getTmBasDeliveryUnitId());
			// 供应商本地标识码
			ttWhmStockOutbound.setTmBasSupplId(listTrBasPartStorage.get(0).getTrBasPartSupplId());
			// 冲销标记
			ttWhmStockOutbound.setFlag(0);
			// 基本单位
			ttWhmStockOutbound.setBaseUnit("EA");
			// 补货需求状态(0:未组织,1:已组织)
			ttWhmStockOutbound.setMriStatus("0");
			// 仓库编号
			ttWhmStockOutbound.setWarehouseNo(listTrBasPartStorage.get(0).getWarehouseNo());
			// 库区编号
			ttWhmStockOutbound.setDlocNo(listTrBasPartStorage.get(0).getDlocNo());
			// 库位编号
			ttWhmStockOutbound.setLocNo(listTrBasPartStorage.get(0).getLocNo());
			ttWhmStockOutbound.setMarkStatus(1);
			ttWhmStockOutbound.setCompanyCode(SpringWebUtils.getRequestCompany());
			ttWhmStockOutbound.setCreateTime(new Date());
			ttWhmStockOutbound.setCreateUser(SpringWebUtils.getRequestUser());
			ttWhmStockOutboundDao.insertNonEmptyTtWhmStockOutbound(ttWhmStockOutbound);

			// 【8】：发运记录表 tt_whm_material_send
			TtWhmMaterialSend ttWhmMaterialSend = new TtWhmMaterialSend();
			// 零件批次属性4
			ttWhmMaterialSend.setPartLotAttr4(twDocOrderDetails.getLotatt04());
			// 零件批次属性3
			ttWhmMaterialSend.setPartLotAttr3(twDocOrderDetails.getLotatt03());
			// 零件批次属性6
			ttWhmMaterialSend.setPartLotAttr6(twDocOrderDetails.getLotatt06());
			// 零件批次属性5
			ttWhmMaterialSend.setPartLotAttr5(twDocOrderDetails.getLotatt05());
			// 零件批次属性8
			ttWhmMaterialSend.setPartLotAttr8(twDocOrderDetails.getLotatt08());
			// 零件批次属性7
			ttWhmMaterialSend.setPartLotAttr7(twDocOrderDetails.getLotatt07());
			// 零件批次属性9
			ttWhmMaterialSend.setPartLotAttr9(twDocOrderDetails.getLotatt09());
			// 零件批次属性2
			ttWhmMaterialSend.setPartLotAttr2(twDocOrderDetails.getLotatt02());
			// 零件批次属性1
			ttWhmMaterialSend.setPartLotAttr1(twDocOrderDetails.getLotatt01());
			// 零件批次属性12
			ttWhmMaterialSend.setPartLotAttr12(twDocOrderDetails.getLotatt12());
			// 零件批次属性11
			ttWhmMaterialSend.setPartLotAttr11(twDocOrderDetails.getLotatt11());
			// 零件批次属性10
			ttWhmMaterialSend.setPartLotAttr10(twDocOrderDetails.getLotatt10());
			// 供应商编号
			ttWhmMaterialSend.setSupplNo(twDocOrderDetails.getSupplNo());
			// 零件号
			ttWhmMaterialSend.setPartNoVersion(twDocOrderDetails.getPartNoVersion());
			// 零件供应商关系ID
			ttWhmMaterialSend.setTrBasPartSupplId(listTrBasPartStorage.get(0).getTrBasPartSupplId());
			// 是否已拣货出库
			ttWhmMaterialSend.setOutboundStatus(1);
			// ttWhmMaterialSend.setDlocPackageSysid(); // 存储包装代码
			// ttWhmMaterialSend.setVin(); // VIN号
			// 发送数量
			ttWhmMaterialSend.setSendQty(twDocOrderDetails.getPickAllocQty());
			// ttWhmMaterialSend.setCurPackageNum(); //当前箱数
			// ttWhmMaterialSend.setSheetItem(); //
			// 发货道口编号
			ttWhmMaterialSend.setSendDockId(twDocOrderDetails.getDockId());
			// 车间
			ttWhmMaterialSend.setTmBasWorkshopId(listTrBasPartStorage.get(0).getTmBasWorkshopId());
			// 发送时间
			ttWhmMaterialSend.setSendTime(new Date());
			// ttWhmMaterialSend.setSheetId(); //对应单证ID
			// 工厂
			ttWhmMaterialSend.setTmBasPlantId(listTrBasPartStorage.get(0).getTmBasPlantId());
			// ttWhmMaterialSend.setFlag(); //冲销标记
			// ttWhmMaterialSend.setCommonSheetType(); // 对应单证类型
			String uudi = UUID.randomUUID().toString();
			ttWhmMaterialSend.setRandNo(uudi.substring(0, 5));
			// ttWhmMaterialSend.setSxCardNo(); // 随箱卡号
			// ttWhmMaterialSend.setOutBoundGroupId(); //出库组号
			// 发送人
			ttWhmMaterialSend.setSendUsername(SpringWebUtils.getRequestUser());
			ttWhmMaterialSend.setDlocId(twDocOrderDetails.getDockId());
			// 供应商号
			ttWhmMaterialSend.setTmBasSupplId(listTrBasPartStorage.get(0).getTrBasPartSupplId());
			// ttWhmMaterialSend.setTmBasPartId(); // 零件 ID
			// 拣货库位
			ttWhmMaterialSend.setDlocId(listTwActAllocLotd.get(0).getActTmBasStorageId());
			// 对应单证编号
			ttWhmMaterialSend.setSheetNo(twDocOrderDetails.getSoSheetNo());
			// ttWhmMaterialSend.setDeliveryRec(); //目的地
			// ttWhmMaterialSend.setTmBasDeliveryUnitId(); //发货地
			// 拣货仓库
			ttWhmMaterialSend.setWarehouseId(listTwActAllocLotd.get(0).getTwActAllocLotdId());
			// 版本控制
			ttWhmMaterialSend.setOptCounter(1);
			// 创建时间
			ttWhmMaterialSend.setCreateTime(new Date());
			// 是否激活
			ttWhmMaterialSend.setMarkStatus(1);
			// 企业代码
			ttWhmMaterialSend.setCompanyCode(SpringWebUtils.getRequestCompany());
			// 创建用户
			ttWhmMaterialSend.setCreateUser(SpringWebUtils.getRequestUser());
			ttWhmMaterialSendDao.insertNonEmptyTtWhmMaterialSend(ttWhmMaterialSend);
		}
	}

	/**
	 * 保存
	 * 
	 * @param enti
	 *            enti
	 */
	@Override
	public void save(TwDocOrderHeader enti) {
		TwDocOrderHeader twDocOrderHeader = twDocOrderHeaderDao.selectTwDocOrderHeaderById(
				enti.getTwDocOrderHeaderId());
		String soSheetStatus = twDocOrderHeader.getSoSheetStatus();
		if (!("0".equals(soSheetStatus))) {
			throw new ServiceException("新单0，才能保存");
		}
		twDocOrderHeaderDao.updateNonEmptyTwDocOrderHeaderById(enti);
	}

	/**
	 * 新增
	 * 
	 * @param value
	 *            value
	 */
	@Override
	public int insertTwDocOrderHeader(TwDocOrderHeader value) {
		String sosheetno = jdbcDao.executeProcGetCode("tw_doc_order_header", "efast");
		value.setSoSheetNo(sosheetno);
		// SO单证状态（新单0、部分分配1、分配完成2、部分拣货3、拣货完成4、部分装箱5、装箱完成6、部分发运7、发运完成8、订单取消9、单证关闭10）
		value.setSoSheetStatus("0");
		// 单证创建时间
		value.setSheetCreateTime(new Date());
		// 创建用户类型(系统自动0，人工1)
		value.setCreateUserType("1");
		value.setMarkStatus(1);
		value.setCreateUser(SpringWebUtils.getRequestUser());
		value.setCompanyCode(SpringWebUtils.getRequestCompany());
		value.setCreateTime(new Date());
		return twDocOrderHeaderDao.insertTwDocOrderHeader(value);
	}

	/**
	 * 删除 === 逻辑删除Header&Detail
	 * 
	 * @param id
	 *            id
	 */
	@Override
	public int deleteTwDocOrderHeaderById(Integer id) {
		TwDocOrderHeader twDocOrderHeader = twDocOrderHeaderDao.selectTwDocOrderHeaderById(id);
		String soSheetStatus = twDocOrderHeader.getSoSheetStatus();
		if (!("0".equals(soSheetStatus))) {
			throw new ServiceException("新单0，才能保存");
		}
		// 先把detail的数据删除
		twDocOrderDetailsDao.deleteTwDocOrderDetails(
				new Assist(Assist.andEq("tw_doc_order_details.tw_doc_order_header_id", id)));
		// 然后删除header的数据
		return twDocOrderHeaderDao.deleteTwDocOrderHeaderById(id);
	}

	/**
	 * 按单关闭 除了已经关闭之外，其余所有状态均可以关闭单据
	 * 
	 * @param enti
	 *            enti
	 */
	@Override
	public int updateNonEmptyTwDocOrderHeaderById(TwDocOrderHeader enti) {
		TwDocOrderHeader twDocOrderHeader = twDocOrderHeaderDao.selectTwDocOrderHeaderById(
				enti.getTwDocOrderHeaderId());
		String soSheetStatus = twDocOrderHeader.getSoSheetStatus();
		if (!("0".equals(soSheetStatus) || "1".equals(soSheetStatus) || "2".equals(soSheetStatus)
				|| "7".equals(soSheetStatus) || "8".equals(soSheetStatus))) {
			throw new ServiceException("新单0,部分分配1,分配完成2,部分发运7,发运完成8,分配失败,才能按单关闭");
		}
		TwDocOrderDetails twDocOrderDetails = new TwDocOrderDetails();
		// 订单行状态（新单0、部分分配1、分配完成2、部分拣货3、拣货完成4、订单取消9、关闭10、分配失败11）
		twDocOrderDetails.setLineStatus("10");
		// 1：把detail的状态置为关闭状态
		twDocOrderDetailsDao.updateNonEmptyTwDocOrderDetails(twDocOrderDetails,
				new Assist(Assist.andEq("tw_doc_order_details.tw_doc_order_header_id", enti.getTwDocOrderHeaderId())));
		// SO单证状态（新单0、部分分配1、分配完成2、部分拣货3、拣货完成4、部分装箱5、装箱完成6、
		// 部分发运7、发运完成8、订单取消9、单证关闭10）
		enti.setSoSheetStatus("10");
		// 2:把header的状态置为关闭状态
		return twDocOrderHeaderDao.updateNonEmptyTwDocOrderHeaderById(enti);
	}

	/**
	 * 取消
	 * 
	 * @param enti
	 *            enti
	 */
	@Override
	public void cancel(TwDocOrderHeader enti) {
		TwDocOrderHeader twDocOrderHeader = twDocOrderHeaderDao.selectTwDocOrderHeaderById(
				enti.getTwDocOrderHeaderId());
		String soSheetStatus = twDocOrderHeader.getSoSheetStatus();
		if (!("0".equals(soSheetStatus) || "1".equals(soSheetStatus) || "2".equals(soSheetStatus))) {
			throw new ServiceException("新单0，部分分配1，分配完成2,才能取消");
		}
		TwDocOrderHeader twDocOrderHeader2 = new TwDocOrderHeader();
		twDocOrderHeader2.setTwDocOrderHeaderId(enti.getTwDocOrderHeaderId());
		twDocOrderHeader2.setSoSheetStatus("9");
		twDocOrderHeaderDao.updateNonEmptyTwDocOrderHeaderById(twDocOrderHeader2);
	}

	/**
	 * 按单生成拣货任务 操作后状态:不变
	 * 
	 * @param enti
	 *            enti
	 */
	@Override
	public void generatePickingByBill(TwDocOrderHeader enti) {
		TwDocOrderHeader twDocOrderHeader = twDocOrderHeaderDao.selectTwDocOrderHeaderById(
				enti.getTwDocOrderHeaderId());
		String soSheetStatus = twDocOrderHeader.getSoSheetStatus();
		if (!("2".equals(soSheetStatus) || "1".equals(soSheetStatus))) {
			throw new ServiceException("分配完成2,部分分配1 状态,才能按单生成拣货任务");
		}
		// 按单生成拣货任务 没有实现
	}

	/**
	 * 取消分配 操作后状态：新单0
	 * 
	 * @param enti
	 *            enti
	 */
	@Override
	public void cancelDistribution(TwDocOrderHeader enti) {
		TwDocOrderHeader twDocOrderHeader = twDocOrderHeaderDao.selectTwDocOrderHeaderById(
				enti.getTwDocOrderHeaderId());
		String soSheetStatus = twDocOrderHeader.getSoSheetStatus();
		if (!("2".equals(soSheetStatus) || "1".equals(soSheetStatus))) {
			throw new ServiceException("当header是:部分分配1或分配完成2状态,才能取消分配");
		}
		TwDocOrderHeader twDocOrderHeader2 = new TwDocOrderHeader();
		twDocOrderHeader2.setTwDocOrderHeaderId(enti.getTwDocOrderHeaderId());
		twDocOrderHeader2.setSoSheetStatus("0");
		twDocOrderHeaderDao.updateNonEmptyTwDocOrderHeaderById(twDocOrderHeader2);
		// 按单生成拣货任务 没有实现
	}

	@Override
	public long getTwDocOrderHeaderRowCount(Assist assist) {
		return twDocOrderHeaderDao.getTwDocOrderHeaderRowCount(assist);
	}

	@Override
	public List<TwDocOrderHeader> selectTwDocOrderHeader(Assist assist) {
		return twDocOrderHeaderDao.selectTwDocOrderHeader(assist);
	}

	@Override
	public TwDocOrderHeader selectTwDocOrderHeaderByObj(TwDocOrderHeader obj) {
		return twDocOrderHeaderDao.selectTwDocOrderHeaderByObj(obj);
	}

	@Override
	public TwDocOrderHeader selectTwDocOrderHeaderById(Integer id) {
		return twDocOrderHeaderDao.selectTwDocOrderHeaderById(id);
	}

	@Override
	public int insertNonEmptyTwDocOrderHeader(TwDocOrderHeader value) {
		return twDocOrderHeaderDao.insertNonEmptyTwDocOrderHeader(value);
	}

	@Override
	public int insertTwDocOrderHeaderByBatch(List<TwDocOrderHeader> value) {
		return twDocOrderHeaderDao.insertTwDocOrderHeaderByBatch(value);
	}

	@Override
	public int deleteTwDocOrderHeader(Assist assist) {
		return twDocOrderHeaderDao.deleteTwDocOrderHeader(assist);
	}

	@Override
	public int updateTwDocOrderHeaderById(TwDocOrderHeader enti) {
		return twDocOrderHeaderDao.updateTwDocOrderHeaderById(enti);
	}

	@Override
	public int updateTwDocOrderHeader(TwDocOrderHeader value, Assist assist) {
		return twDocOrderHeaderDao.updateTwDocOrderHeader(value, assist);
	}

	@Override
	public int updateNonEmptyTwDocOrderHeader(TwDocOrderHeader value, Assist assist) {
		return twDocOrderHeaderDao.updateNonEmptyTwDocOrderHeader(value, assist);
	}

}